﻿namespace BM.Tools.WebControls.MForm.Controls.Modifiers
{
    using System;
    using System.ComponentModel;
    using System.Globalization;
    using System.Linq;
    using System.Text;
    using System.Web.UI;
    using System.Web.UI.WebControls;

    using BM.Tools.WebControls.MForm.Controls.Helper;
    using BM.Tools.WebControls.MForm.Controls.Items;
    using BM.Tools.WebControls.MForm.Controls.Modifiers.Additions;
    using BM.Tools.WebControls.MForm.Navigation;
    using BM.Tools.WebControls.MForm.ScriptReferences;

    /// <summary>
    /// A modifier that changes the display of the control, to look like a table.
    /// the children are laid out vertically, and the siblings are laid out horizontally.
    /// </summary>
    public class VerticalTableDisplayModifier : TableDisplayModifier, IDisposable
    {
        private const string VerticalHeaderCssClass = "MForm-VHead";

        private const string VerticalRecordCssClass = "MForm-VRow";

        private FormStyle cellStyle;

        private FormStyle columnStyle;

        /// <summary>
        /// Gets CellStyle.
        /// </summary>
        /// <value>
        /// The cell style.
        /// </value>
        [PersistenceMode(PersistenceMode.InnerProperty)]
        [NotifyParentProperty(true)]
        [Category("Styles")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public FormStyle CellStyle
        {
            get
            {
                if (cellStyle == null)
                {
                    cellStyle = new FormStyle();
                }

                return cellStyle;
            }
        }

        /// <summary>
        /// Gets ColumnStyle.
        /// </summary>
        /// <value>
        /// The column style.
        /// </value>
        [PersistenceMode(PersistenceMode.InnerProperty)]
        [NotifyParentProperty(true)]
        [Category("Styles")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public FormStyle ColumnStyle
        {
            get
            {
                if (columnStyle == null)
                {
                    columnStyle = new FormStyle();
                }

                return columnStyle;
            }
        }

        /// <summary>
        /// Gets TitleCssClass.
        /// </summary>
        protected override string TitleCssClass
        {
            get
            {
                return VerticalHeaderCssClass;
            }
        }

        /// <summary>
        /// Disposes the control
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Registers styles on the page so that items look like a table.
        /// </summary>
        /// <param name="offspring">
        /// The offspring.
        /// </param>
        protected override void AddStyles(OffspringsOwner offspring)
        {
            string columnWidth = Convert.ToString(99 / (GetColumnCount(offspring) + 1), CultureInfo.InvariantCulture)
                                 + "%";
            string siblingsCss = GetCommonSiblingsHash(offspring);
            ColumnStyle.Width = new Unit(columnWidth, CultureInfo.InvariantCulture);
            ColumnStyle.Left = new Unit(columnWidth, CultureInfo.InvariantCulture);
            ScriptIncluder.CreateOrGetHeader(offspring.Page).StyleSheet.CreateStyleRule(
                    ColumnStyle, null, String.Concat(".", siblingsCss));
            ScriptIncluder.CreateOrGetHeader(offspring.Page).StyleSheet.CreateStyleRule(
                    CellStyle, null, String.Concat(".", siblingsCss, " ." + LeafItem.LeafCssClass));
        }

        /// <summary>
        /// Disposes the control
        /// </summary>
        /// <param name="disposing">
        /// The disposing.
        /// </param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (columnStyle != null)
                {
                    columnStyle.Dispose();
                }

                if (cellStyle != null)
                {
                    cellStyle.Dispose();
                }
            }
        }

        /// <summary>
        /// Creates css styles for children, adds css classes to children, add vertical table display addition
        /// </summary>
        /// <param name="offspringItem">
        /// The offspring item.
        /// </param>
        /// <param name="args">
        /// The event args.
        /// </param>
        protected override void OnItemPreRender(OffspringsOwnerItem offspringItem, EventArgs args)
        {
            string siblingsCss = GetCommonSiblingsHash(offspringItem.Basis);

            offspringItem.Title.Text = string.Empty;
            offspringItem.CssClasses.Add(VerticalRecordCssClass, siblingsCss);
            offspringItem.Additions.Add(new VerticalTableDisplayAddition());
        }

        private static int GetColumnCount(Offspring offspring)
        {
            return offspring.Items.Where(item => !item.IsPrototypeDescendant()).Count();
        }

        /// <summary>
        /// returns a common string hash for all offspring item siblings
        /// </summary>
        /// <param name="offspring">
        /// The offspring.
        /// </param>
        /// <returns>
        /// the string hash.
        /// </returns>
        private static string GetCommonSiblingsHash(Control offspring)
        {
            var builder = new StringBuilder("Table_" + offspring.ClientID + "_");
            builder.Replace("-", string.Empty);
            builder.Replace(":", string.Empty);
            return builder.ToString();
        }
    }
}